package org.rency.common.memcache.dao;

import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.rency.common.memcache.bean.MemcacheNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.support.JdbcDaoSupport;

public class NodeDaoImpl extends JdbcDaoSupport implements NodeDao {
	
	private static final Logger logger = LoggerFactory.getLogger(NodeDaoImpl.class);
	
	private final String SQL_TABLE_NAME = "tc_memcache_node";
	
	private final String SQL_CREATE_TABLE = "create table "+SQL_TABLE_NAME+" (ID int auto_increment primary key,NODE_HOST varchar(30) not null comment '节点域名',NODE_PORT smallint(8) not null comment '节点端口',NODE_WEIGHT smallint(4) not null comment '节点权重',UPDATE_TIME timestamp default CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,CREATE_TIME timestamp not null default '0000-00-00 00:00:00',MEMO varchar(200) comment '备注') comment='Memcached节点配置' ENGINE=InnoDB DEFAULT CHARSET=utf8";

	private final String SQL_LOAD_ALL = " select * from "+SQL_TABLE_NAME;
	
	private final String SQL_LOAD = " select * from "+SQL_TABLE_NAME+" where ID = ?";
	
	private final String SQL_SAVE = " insert into "+SQL_TABLE_NAME+"(ID,NODE_HOST,NODE_PORT,NODE_WEIGHT,CREATE_TIME,MEMO) values(?,?,?,?,?,?,?)";
	
	private final String SQL_UPDATE_WEIGHT = "update from "+SQL_TABLE_NAME+" set NODE_WEIGHT = ? where ID = ?";
	
	private final String SQL_DELETE = "delete "+SQL_TABLE_NAME+" where ID = ?";
	
	private RowMapper<MemcacheNode> rowMapper = new RowMapper<MemcacheNode>() {
		@Override
		public MemcacheNode mapRow(ResultSet rs, int param) throws SQLException {
			MemcacheNode node = new MemcacheNode();
			node.setId(rs.getInt("ID"));
			node.setNodeHost(rs.getString("NODE_HOST"));
			node.setNodePort(rs.getInt("NODE_PORT"));
			node.setNodeWeight(rs.getInt("NODE_WEIGHT"));
			node.setCreateTime(rs.getDate("CREATE_TIME"));
			node.setUpdateTime(rs.getDate("UPDATE_TIME"));
			node.setMemo(rs.getString("MEMO"));
			return node;
		}
	};
	
	@Override
	public List<MemcacheNode> loadAll() {
		return super.getJdbcTemplate().query(SQL_LOAD_ALL,rowMapper);
	}

	@Override
	public MemcacheNode load(Integer id) {
		List<MemcacheNode> nodes = super.getJdbcTemplate().query(SQL_LOAD,new Object[]{id},rowMapper);
		if(nodes != null && nodes.size() > 0){
			return nodes.get(0);
		}else{
			return null;
		}
	}

	@Override
	public boolean save(MemcacheNode node) {
		return super.getJdbcTemplate().update(SQL_SAVE, new Object[]{node.getId(),node.getNodeHost(),node.getNodePort(),node.getNodeWeight(),node.getCreateTime(),node.getMemo()}) > 0;
	}

	@Override
	public boolean updateWeight(Integer id, Integer weight) {
		return super.getJdbcTemplate().update(SQL_UPDATE_WEIGHT, new Object[]{id,weight}) > 0;
	}

	@Override
	public boolean delete(Integer id) {
		return super.getJdbcTemplate().update(SQL_DELETE, new Object[]{id}) > 0;
	}

	
	@Override
	public void createTable() {
		logger.info("执行Memcache缓存脚本...");
		try {
			DatabaseMetaData metaData = super.getDataSource().getConnection().getMetaData();
			if(isExists(SQL_TABLE_NAME,metaData)){
				return;
			}
			super.getJdbcTemplate().execute(SQL_CREATE_TABLE);
		} catch (SQLException e) {
			logger.error("执行Memcache缓存脚本发生异常,{}.",SQL_CREATE_TABLE,e);
		}
		logger.info("执行Memcache缓存脚本完成...");
	}
	
	/**
	 * 判断数据表是否存在
	 * </br>Created on 2016年4月15日
	 * @param tableName
	 * @param metaData
	 * @return
	 * @throws SQLException
	 */
	private boolean isExists(String tableName,DatabaseMetaData metaData) throws SQLException{
		ResultSet rs = null;
		try {
			rs = metaData.getTables(null, null, tableName, new String[]{"TABLE"});
			if(rs.next()){
				return true;
			}
		} catch (SQLException e) {
			logger.error("判断数据表是否存在异常,表名:{}.",tableName,e);
		}finally{
			if(rs != null){
				try {
					rs.close();
				} catch (SQLException e) {
				}
			}
		}
		return false;
	}

}
